#include "Socket.h"
#include "Logger.h"

#include <netinet/tcp.h>
#include <unistd.h>     //unix和linux中：进程、文件、
#include <sys/socket.h>
#include <sys/types.h>
#include <strings.h>

Socket::~Socket(){
    ::close(sockfd_);   //??头文件unistd，注意要使用::
}

void Socket::bindAddress(const InetAddress &localaddr){
    if(::bind(sockfd_, (sockaddr*)localaddr.getsocketAddr(), sizeof(sockaddr_in)) != 0){
        //这里的sockaddr_in是可以向sockaddr转换的，只需要在显示声明一下即可
        LOG_FATAL("func %s, sockfd listen %d fail \n", __FUNCTION__, sockfd_);
    }
}

void Socket::listen(){
    if(::listen(sockfd_, 1024) != 0){
        LOG_FATAL("func %s, sockfd listen %d fail \n", __FUNCTION__, sockfd_);
    }
}

int Socket::accept(InetAddress *perraddr){
    //这里的第二个参数是传出参数
    sockaddr_in addr;
    socklen_t len;
    bzero(&addr, sizeof(addr));
    int connfd = ::accept(sockfd_, (sockaddr*)(&addr), &len);
    if(connfd >= 0){
        perraddr->setsockAddr(addr);    //将客户端的网络地址信息保存到 perraddr 所指向的对象
    }
    return connfd;
}

void Socket::shutdownWrite(){
    if(::shutdown(sockfd_, SHUT_WR) < 0){
        LOG_ERROR("func %s, shutdown error %d \n", __FUNCTION__, sockfd_);
    }
}

void Socket::setTcpNoDelay(bool on){
    int optval = on ? 1 : 0;
    ::setsockopt(sockfd_, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));
}

void Socket::setReuseAddr(bool on){
    int optval = on ? 1 : 0;
    ::setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
}

void Socket::setReusePort(bool on){
    int optval = on ? 1 : 0;
    ::setsockopt(sockfd_, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
}
    
void Socket::setKeepAlive(bool on){
    int optval = on ? 1 : 0;
    ::setsockopt(sockfd_, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval));
}